/*
 * Copyright (C) 2007 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.example.p4;

import java.util.ArrayList;

import com.example.p4.R;

import android.annotation.TargetApi;
import android.content.Context;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;
import android.os.Bundle;

/**
 * SnakeView: implementation of a simple game of Snake
 */
@TargetApi(10)
public class PopBubbleView extends View {

	Paint paint = new Paint();
	
	protected int screenWidth;
    protected int screenHeight;
    
    Bitmap[] images;
    
    protected ArrayList<Ball> balls;
	
    /**
     * Labels for the drawables that will be loaded into the TileView class
     */
	
    static final int BLUE = 1;
    static final int RED = 2;
    static final int YELLOW = 3;
    static final int GREEN = 4;
    static final int PURPLE = 5;
    private static final int TIME_BAR = 6;
    private static final int TIME_BAR_BACK = 7;
    private static final int WIN = 8;
    private static final int LOSE = 9;
    private static final int BGR = 10;
    
    
    public static final int MODE_RUNNING = 1;
    public static final int MODE_WIN = 2;
    public static final int MODE_LOSE = 3;
    
    //Current game mode
    public int mode = MODE_RUNNING;

    //Number of maze levels deep
    protected static int numOfLevels = 3;
    
    //Level height in tiles
    protected int levelHeight = 0;
    
    //Current depth of player's mouse
    protected int currentLevel = 0;
    
    //Last valid point that the user "touched"
    protected Coordinate lastValidPoint = new Coordinate(0,0);
    
    //Progress Bar Images
    protected Drawable progressBar;
    protected Drawable progressBarBack;
    
    //Time left in game
    
    public double progressBarPercent = 0;
    /**
     * mScore: used to track the number of apples captured mMoveDelay: number of
     * milliseconds between snake movements. This will decrease as apples are
     * captured.
     */
    long mScore = 0;

    /**
     * Constructs a SnakeView based on inflation from XML
     */
    public PopBubbleView(Context context, AttributeSet attrs) {
        super(context, attrs);
        initSnakeView();
   }

    public PopBubbleView(Context context, AttributeSet attrs, int defStyle) {
    	super(context, attrs, defStyle);
    	initSnakeView();
    }
    
    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
    	
    	h-=70; //Make room for Progress Bar at bottom of screen
    	screenWidth = w;
    	screenHeight = h;
    	
        clearScreen();
    }
    
    void setScreenResolution(int h, int w)
    {
    	h-=70; //Make room for Progress Bar at bottom of screen
    	screenWidth = w;
    	screenHeight = h;
    	
        clearScreen();
    }
    
    public void clearScreen()
    {
    	//Clear drawable objects?
    }
    
    public void loadSizedTile(int key, Drawable tile, int x, int y)
    {
    	Bitmap bitmap = Bitmap.createBitmap(x, y, Bitmap.Config.ARGB_8888);
        Canvas canvas = new Canvas(bitmap);
        tile.setBounds(0, 0, x, y);
        tile.draw(canvas);
        
        //Do something with bitmap...
        images[key] = bitmap;
    }
    
    public int getBallWidth()
    {
    	return images[BLUE].getWidth();
    }
    
    public int getBallHeight()
    {
    	return images[BLUE].getHeight();
    }
    
    void initSnakeView() {
        setFocusable(true);
    }
    
    private void resetImages(int numOfImages)
    {
    	if(images != null)
    		for(int i=0; i<images.length; i++)
    			if(images[i] != null)
    				images[i].recycle();
    	
    	images = new Bitmap[numOfImages];
    }
    
    public void resetBalls(int numOfRows)
    {
    	balls = new ArrayList<Ball>();
    	
    	int titleHeight = (int)(screenHeight*0.18);
    	
    	int xOffset = (screenWidth  / numOfRows);
    	int yOffset = (int)((double)(screenHeight-titleHeight) / numOfRows);
    	
    	for(int i=0; i<numOfRows; i++)
    	{
    		int y = (yOffset*i) + (yOffset/8) + titleHeight; // 100 pixels at top to say "CLICK RED"
    		for(int j=0; j<numOfRows; j++)
    		{
    			int x = (xOffset*j) + (xOffset/8);
        		
        		int imageIndex = (int)(Math.random()*5) + 1;
        		balls.add(new Ball(x, y, 0, 0, imageIndex));
    		}
    	}
    }
    
    private void initImages(int numberOfRows)
    {
    	 int balloonWidth  = (int)((3*screenWidth)/(4*numberOfRows));
    	 int balloonHeight = balloonWidth;
    	 
    	 resetImages(11);
    	 Resources r = this.getContext().getResources();
    	 loadSizedTile(BLUE,          r.getDrawable(R.drawable.popbubble_blue),          balloonWidth, balloonHeight);
    	 loadSizedTile(RED,           r.getDrawable(R.drawable.popbubble_red),           balloonWidth, balloonHeight);
    	 loadSizedTile(YELLOW,        r.getDrawable(R.drawable.popbubble_yellow),        balloonWidth, balloonHeight);
    	 loadSizedTile(GREEN,         r.getDrawable(R.drawable.popbubble_green),         balloonWidth, balloonHeight);
    	 loadSizedTile(PURPLE,        r.getDrawable(R.drawable.popbubble_purple),        balloonWidth, balloonHeight);
         loadSizedTile(TIME_BAR,      r.getDrawable(R.drawable.progressbar),   screenWidth, 70);
         loadSizedTile(TIME_BAR_BACK, r.getDrawable(R.drawable.bright),        screenWidth, 70);
         loadSizedTile(WIN,           r.getDrawable(R.drawable.checkmark),     screenWidth, screenHeight);
         loadSizedTile(LOSE,          r.getDrawable(R.drawable.xmark),         screenWidth, screenHeight);
         loadSizedTile(BGR,           r.getDrawable(R.drawable.popbubble_bgr),           screenWidth, screenHeight);
         
         progressBar =     (r.getDrawable(R.drawable.progressbar));
         progressBarBack = (r.getDrawable(R.drawable.bright));
         
         progressBar.setBounds    (0, screenHeight, screenWidth, screenHeight+70);
         progressBarBack.setBounds(0, screenHeight, screenWidth, screenHeight+70);
    }

    void initNewGame(int numberOfBalloons) {
    	setFocusable(true);
        
        resetBalls(numberOfBalloons);
        
        initImages(numberOfBalloons);
        
        paint = new Paint();
    }
    
    void resetGame()
    {
    	/*if(images != null)
    	{
    		for(int i=0; i<images.length; i++)
    		{
    			if(images[i] != null)
    				images[i].recycle();
    		}
    	}*/
    	
    	
    	balls = new ArrayList<Ball>();
    	paint = new Paint();
    	lastValidPoint = new Coordinate(0,0);
    	progressBarPercent = 0;
    	Log.d("GameEvent", "Resetting game");
    }

    /**
     * Save game state so that the user does not lose anything
     * if the game process is killed while we are in the 
     * background.
     * 
     * @return a Bundle with this view's state
     */
    public Bundle saveState() {
        Bundle map = new Bundle();
        map.putLong("mScore", Long.valueOf(mScore));
        return map;
    }

    public void drawProgressBar(Canvas canvas)
    {
    	paint.setColor(Color.DKGRAY);
        if(progressBarBack != null){
        	progressBarBack.draw(canvas);
        	
        	Rect rect = progressBarBack.getBounds();
        	int barWidth = (int)(screenWidth*.92);
        	canvas.drawRect((float) ((barWidth - (barWidth*progressBarPercent))), rect.top, rect.right, rect.bottom, paint);
        }
        if(progressBar != null)
        	progressBar.draw(canvas);
    }
    
    @Override
    public void onDraw(Canvas canvas) {
    	
    	if(images != null)
    	{
	    	drawBackground(canvas);
	    	drawBalls(canvas);
	    	drawWinOrLose(canvas);
    	}
        drawProgressBar(canvas);
        super.onDraw(canvas);
    }
    
    private void drawWinOrLose(Canvas canvas)
    {
    	if(mode == MODE_WIN)
    		canvas.drawBitmap(images[WIN], 0, 0, paint);
    	else if(mode == MODE_LOSE)
    		canvas.drawBitmap(images[LOSE], 0, 0, paint);
    	
    	if(mode == MODE_LOSE)
    		Log.d("GameEvent", "Drawing X");
    }
    
    public void setMode(int newMode)
    {
    	mode = newMode;
    }
    
    private void drawBackground(Canvas canvas)
    {
    	if(images[BGR].isRecycled())
    		return;
    	canvas.drawBitmap(images[BGR], 0, 0, paint);
    }
    
    public void drawBalls(Canvas canvas)
    {
    	for(int i=0; i<balls.size(); i++)
    		canvas.drawBitmap(images[balls.get(i).imageIndex], balls.get(i).x, balls.get(i).y, paint);
    }

    
    /**
     * Simple class containing two integer values and a comparison function.
     * There's probably something I should use instead, but this was quick and
     * easy to build.
     * 
     */
    public class Coordinate {
        public int x;
        public int y;

        public Coordinate(int newX, int newY) {
            x = newX;
            y = newY;
        }

        public boolean equals(Coordinate other) {
            if (x == other.x && y == other.y) {
                return true;
            }
            return false;
        }

        @Override
        public String toString() {
            return "Coordinate: [" + x + "," + y + "]";
        }
    }
    
    public class Ball extends Coordinate
    {
    	public Ball(int newX, int newY, double newdX, double newdY, int newImageIndex) {
			super(newX, newY);
			dX = newdX;
			dY = newdY;
			imageIndex = newImageIndex;
		}
		public double dX;
    	public double dY;
    	public int imageIndex;
    	
    	public void move(int lowX, int lowY, int highX, int highY)
    	{
    		if(x+dX < lowX)
    		{
    			x = lowX;
    			dX = -dX;
    		}
    		else if(x+dX > highX)
    		{
    			x = highX;
    			dX = -dX;
    		}
    		else
    			x += dX;
    		
    		if(y+dY < lowY)
    		{
    			y = lowY;
    			dY = -dY;
    		}
    		else if(y+dY > highY)
    		{
    			y = highY;
    			dY = -dY;
    		}
    		else
    			y += dY;
    	}
    }
    
}
